package cn.yudao.ymcc.service.impl;

import cn.yudao.ymcc.constant.PayType;
import cn.yudao.ymcc.domain.AlipayInfo;
import cn.yudao.ymcc.domain.PayOrder;
import cn.yudao.ymcc.dto.Order2PayTranMesDto;
import cn.yudao.ymcc.dto.PayParmDto;
import cn.yudao.ymcc.mapper.PayOrderMapper;
import cn.yudao.ymcc.service.IAlipayInfoService;
import cn.yudao.ymcc.service.IPayOrderService;
import cn.yudao.ymcc.utils.AssertUtil;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.kernel.util.ResponseChecker;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author whale.jia
 * @since 2022-08-18
 */
@Service
public class PayOrderServiceImpl extends ServiceImpl<PayOrderMapper, PayOrder> implements IPayOrderService {

    @Autowired
    private IAlipayInfoService infoService;


    /**
    * @Title: savePayOrderByOrder
    * @Description: 根据订单添加支付单信息
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/20 12:47
    * @Parameters:
    * @Return
    */
    @Override
    @Transactional
    public void savePayOrderByOrder(Order2PayTranMesDto mediaFile) {
        PayOrder payOrder = getPayOrder(mediaFile.getOrderNo());

        AssertUtil.isNull(payOrder,"请勿重复提交");
        // 填充数据
        payOrder = new PayOrder();
        BeanUtils.copyProperties(mediaFile,payOrder);
        Date now = new Date();
        payOrder.setCreateTime(now);
        payOrder.setPayStatus(PayOrder.WAIT_STATUS);

        // 新增数据库
        insert(payOrder);
    }


    @Override
    public PayOrder getPayOrder(String orderNo) {
        // 先查询是否具有当前支付单 根据订单号查询
        Wrapper<PayOrder> wrapper = new EntityWrapper<>();
        wrapper.eq("order_no", orderNo);
        PayOrder payOrder = selectOne(wrapper);
        return payOrder;
    }

    /**
    * @Title: checkPayOrder
    * @Description: 轮询查找有无当前订单
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/20 15:56
    * @Parameters:
    * @Return
    */
    @Override
    public boolean checkPayOrder(String orderNo) {
        PayOrder payOrder = getPayOrder(orderNo);
        if (payOrder == null){
            return false;
        }
        return true;
    }

    /**
    * @Title: payOrder
    * @Description: 获取支付页面
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/20 16:07
    * @Parameters:
    * @Return
    */
    @Override
    public String payOrder(PayParmDto dto) {
        // 非空判断JSR303
        // 判断订单状态是否已支付状态
        PayOrder payOrder = getPayOrder(dto.getOrderNo());
        AssertUtil.isNotNull(payOrder,"请求支付超时");
        AssertUtil.isTrue(payOrder.getPayStatus() == PayOrder.WAIT_STATUS,"请重新下单支付");
        // 调用支付页面-- 判断支付类型--支付宝支付还是微信支付等其他支付方式
        if (dto.getPayType() == PayType.pay_alibaba){
            String payAlibaba = payAlibaba(payOrder, dto);
            AssertUtil.isNotNull(payAlibaba,"支付页面跳转失败");
            return payAlibaba;
        }// 后面做其他判断支付---没写

        return null;
    }

    /**
    * @Title: PayOrderLevel
    * @Description: 订单超时处理
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/21 20:00
    * @Parameters:
    * @Return
    */
    @Override
    public void PayOrderLevel(String orderNo) {
        // 查询支付表
        PayOrder payOrder = getPayOrder(orderNo);
        // 判断支付表的状态
        if (payOrder.getPayStatus() == PayOrder.WAIT_STATUS){ // 判断是否为待支付
            // 设置状态
            payOrder.setPayStatus(PayOrder.OUT_TIME_STATUS); // 设置超时
            // 设置修改时间
            payOrder.setUpdateTime(new Date());
            // 修改数据库
            updateById(payOrder);
            // 调用支付宝取消本次交易
            try {
                Factory.Payment.Common().close(orderNo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
    * @Title: payAlibaba
    * @Description: 获取支付宝支付界面
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/21 20:00
    * @Parameters:
    * @Return
    */
    public String payAlibaba(PayOrder payOrder, PayParmDto dto) {
        // 1. 设置参数（全局只需设置一次）
        // 获取参数值
        AlipayInfo alipayInfo = infoService.selectList(null).get(0); // 从数据库中查询到需要的参数
        Factory.setOptions(getOptions(alipayInfo));
        try {
            // 2.网页支付
            AlipayTradePagePayResponse response = Factory.Payment.Page().pay(
                    payOrder.getSubject(), // 标题
                    payOrder.getOrderNo(), // 订单号
                    payOrder.getAmount().toString(), // 支付金额
                    dto.getCallUrl() == null?alipayInfo.getReturnUrl():dto.getCallUrl() // 支付完成跳转地址
            );
            // 3. 处理响应或异常
            if (ResponseChecker.success(response)) {
                System.out.println("调用成功");
                return response.getBody();
            } else {

                System.err.println("调用失败，原因：" + response);
            }
        } catch (Exception e) {
            System.err.println("调用遭遇异常，原因：" + e.getMessage());
            throw new RuntimeException(e.getMessage(), e);
        }
        return null;
    }


    /**
    * @Title: getOptions
    * @Description: 支付宝需要的参数
    * @Author: Mr.Jia
    * @Version: 1.0
    * @Date:  2022/8/21 20:00
    * @Parameters:
    * @Return
    */
    private Config getOptions(AlipayInfo alipayInfo) {
        Config config = new Config();
        config.protocol = alipayInfo.getProtocol();
        config.gatewayHost = alipayInfo.getGatewayHost();
        config.signType = alipayInfo.getSignType();
        config.appId = alipayInfo.getAppId();
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        config.merchantPrivateKey = alipayInfo.getMerchantPrivateKey();
        //注：如果采用非证书模式，则无需赋值上面的三个证书路径，改为赋值如下的支付宝公钥字符串即可
        config.alipayPublicKey = alipayInfo.getAlipayPublicKey();
        //可设置异步通知接收服务地址（可选）
        config.notifyUrl = alipayInfo.getNotifyUrl();
        return config;
    }




}
